package it.uniroma3.dia.mysql;

import it.uniroma3.dia.accesso.TwitterWrapper;
import it.uniroma3.dia.filtro_amici.FiltroAmici;
import it.uniroma3.dia.filtro_amici.FiltroAmiciPerNumeroMinimoFollowers;

import java.sql.Connection;
import java.sql.Date;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
//import java.util.Collection;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;

import it.uniroma3.dia.mysql.Connector;

//import david.twitter.analyze.TweetAnalyzer;

//import winterwell.jtwitter.Twitter;
import winterwell.jtwitter.Twitter.Status;
import winterwell.jtwitter.Twitter.User;


/*classe responsabile di verificare la presenza di informazioni nel db in modo da non scaricarle piu volte.
 * Le info riguardano gli utenti e i loro amici
 */
public class DBCache {
	
	private Connection connection;
	
	private static DBCache instance;

	
	public static DBCache getInstance() {
		if (instance == null)
			instance = new DBCache();		
		return instance;
	}
	
	
	
	

	
	//non prevede caching degli amici, gli amici vengono scaricati ogni volta dalle api
	//ed inseriti nel db controllando i duplicati
	public List<User> getAmici_2(TwitterWrapper twitter, User user){
		int id;
		List<User> amici = new LinkedList<User>();
		connection = Connector.getInstance().connetti();
		FiltroAmici filtro = new FiltroAmiciPerNumeroMinimoFollowers();
		
		//scarico gli amici dell'utente da Twitter
		System.out.println("Download amici di " + user.getScreenName());
		amici = twitter.getFriends(user.getScreenName());
		
		//filtro gli amici
		//considero solo gli amici che mi interessano
		filtro.filtraAmici(amici);
		
		//inserisco con controllo duplicati nel db, inserisco con la data 
		//in cui sono stati scaricati
		Statement stat;
		Tweet2db t2d = Tweet2db.getInstance();
		
		try {
			//LOCK UTENTI, AMICI
			stat = connection.createStatement();
			stat.execute("LOCK TABLES utenti READ, amici WRITE");
			
			t2d.inserisciAmici(user.getScreenName(), amici);
			
			//UNLOCK UTENTI,AMICI
			stat = connection.createStatement();
			stat.executeUpdate("UNLOCK TABLES"); 
			stat.close();

			Connector.getInstance().disconnetti();

		} catch (SQLException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		
		return amici;
		
	}





	//ritorna gli amici eventualmente presenti nel db
	public List<User> getAmici(TwitterWrapper twitter, User user) {
		int id;
		List<User> amici = new LinkedList<User>();
		connection = Connector.getInstance().connetti();
		FiltroAmici filtro = new FiltroAmiciPerNumeroMinimoFollowers();

		
		//verifico se nel db sono presenti gli amici dell'utente
		ResultSet rs;
		String query = "SELECT amici.username FROM (utenti JOIN amici) WHERE (utenti.screen_name = ? AND amici.cod_utente = utenti.id)";
		PreparedStatement stmt;
		Statement stat;
		
		try {
			//LOCK UTENTI, AMICI
			stat = connection.createStatement();
			stat.execute("LOCK TABLES utenti READ, amici READ"); 

			stmt = connection.prepareStatement(query);
			stmt.setString(1, user.getScreenName());
			rs = stmt.executeQuery();
			
			if (rs.next()){				
				//gli amici sono gi� in cache
				System.out.println("Amici in cache per " + user.getScreenName());
				amici.add(new User(rs.getString(1)));
				while(rs.next()){
					amici.add(new User(rs.getString(1)));
				}
				//UNLOCK UTENTI,AMICI
				stat = connection.createStatement();
				stat.executeUpdate("UNLOCK TABLES"); 

			}else{
				//UNLOCK UTENTI,AMICI, necessario rilasciare il lock perch� getFriends via http molto lento
				stat = connection.createStatement();
				stat.executeUpdate("UNLOCK TABLES"); 
				
				System.out.println("Download amici di " + user.getScreenName());
				//gli amici non sono in cache, li ricavo dalle api di twitter e poi li memorizzo in cache
				amici = twitter.getFriends(user.getScreenName());
				
				//considero solo gli amici che mi interessano
				filtro.filtraAmici(amici);
				
				//LOCK UTENTI, AMICI
				stat = connection.createStatement();
				stat.execute("LOCK TABLES utenti READ, amici WRITE");
				
				//verifico di nuovo la presenza di amici in quanto avendo rilasciato il lock per non occupare eccessivamente il db
				//c'� il rischio che gli stessi amici vengano inseriti pi� volte
				query = "SELECT amici.username FROM (utenti JOIN amici) WHERE (utenti.screen_name = ? AND amici.cod_utente = utenti.id)";
				stmt= connection.prepareStatement(query);
				stmt.setString(1, user.getScreenName());
				rs = stmt.executeQuery();
				if (!rs.next()){	
					//ricavo l'id dell'utente attuale (user)
					query = "SELECT id FROM utenti WHERE (screen_name = ?)";
					stmt = connection.prepareStatement(query);
					stmt.setString(1, user.getScreenName());
					rs = stmt.executeQuery();

					if(rs.next()){
						id = rs.getInt(1);

						query = "INSERT INTO  amici (username, cod_utente) VALUES (?,?)";
						for(User u : amici){
							stmt = connection.prepareStatement(query);
							stmt.setString(1, u.getScreenName());
							stmt.setInt(2, id);
							stmt.executeUpdate();
						}
					}	
					//UNLOCK UTENTI,AMICI
					stat = connection.createStatement();
					stat.executeUpdate("UNLOCK TABLES");
				}
				
			}
			rs.close();
			stmt.close();
			stat.close();
			Connector.getInstance().disconnetti();
				
		} catch (SQLException e) {
			e.printStackTrace();
		}
	
		return amici;
	}



//	public void processaTimeline(TwitterWrapper twitter, User user) {
//		this.nuovaTimeline(twitter, user);
//				
//	}





	public List<User> getAmiciNoFilter(TwitterWrapper twitter, User user) {
		int id;
		List<User> amici = new LinkedList<User>();
		connection = Connector.getInstance().connetti();
		FiltroAmici filtro = new FiltroAmiciPerNumeroMinimoFollowers();
		
		//scarico gli amici dell'utente da Twitter
		System.out.println("Download amici di " + user.getScreenName());
		amici = twitter.getFriends(user.getScreenName());
		System.out.println("amici " + user.getScreenName() + " = " + amici.size());
		
		
		//inserisco con controllo duplicati nel db, inserisco con la data 
		//in cui sono stati scaricati
		Statement stat;
		Tweet2db t2d = Tweet2db.getInstance();
		
		try {
			//LOCK UTENTI, AMICI
			stat = connection.createStatement();
			stat.execute("LOCK TABLES utenti WRITE, amici WRITE");
			t2d.nuovoUtente(user.getScreenName());
			t2d.inserisciAmici(user.getScreenName(), amici);
			
			//UNLOCK UTENTI,AMICI
			stat = connection.createStatement();
			stat.executeUpdate("UNLOCK TABLES"); 
			stat.close();

			Connector.getInstance().disconnetti();

		} catch (SQLException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		
		return amici;
	}

	
	
public HashMap<Integer, LinkedList<User>> getCluster2DB(User rootUser)
	
	{
		HashMap<Integer, LinkedList<User>> cluster2utenti = new HashMap<Integer, LinkedList<User>>();
		List<User>c1 = new LinkedList<User>();
		List<User>c2 = new LinkedList<User>();
		List<User>c3 = new LinkedList<User>();
		List<User>c4 = new LinkedList<User>();
		Connection connection = Connector.getInstance().connetti();
		ResultSet rs;
		
			String query="SELECT cluster_name, utente FROM cluster WHERE (rootuser= ?)";
			PreparedStatement stmt;
		try {
			
			stmt = connection.prepareStatement(query);
			stmt.setString(1, rootUser.getScreenName());
			rs = stmt.executeQuery();
			while (rs.next())
			{
				if(rs.getInt("cluster_name")==1)
				{
					c1.add(new User(rs.getString("utente")));
				}
				if(rs.getInt("cluster_name")==2)
				{
					c2.add(new User(rs.getString("utente")));
				}
				if(rs.getInt("cluster_name")==3)
				{
					c3.add(new User(rs.getString("utente")));
				}
				if(rs.getInt("cluster_name")==4)
				{
					c4.add(new User(rs.getString("utente")));
				}
				
			}									
		    rs.close();
			stmt.close();
				
		} catch (SQLException e) {
			e.printStackTrace();
			System.out.println("Utente non presente.");
		}
		cluster2utenti.put(1, (LinkedList<User>) c1);
		cluster2utenti.put(2, (LinkedList<User>) c2);
		cluster2utenti.put(3, (LinkedList<User>) c3);
		cluster2utenti.put(4, (LinkedList<User>) c4);
		
		
		return cluster2utenti;
		
	}
}
